Use case: Communication in interrupt mode

The FDCAN interrupt management has been updated to use a more modular approach.

  • Interrupt to line configuration:

    In HAL1, the configuration of FDCAN interrupt lines is performed using the HAL_FDCAN_ConfigInterruptLines() function. When interrupt grouping is supported by the given STM32 device, grouped interrupt flags such as FDCAN_IT_GROUP_SMSG and FDCAN_IT_GROUP_RX_FIFO0 are collectively assigned to the chosen interrupt line (line 0 and/or line 1). If interrupt grouping is not supported by the device, individual interrupt sources like FDCAN_IT_TX_COMPLETE and FDCAN_IT_RX_FIFO0_NEW_MESSAGE are assigned directly to the chosen interrupt line (line 0 and/or line 1).

    In HAL2, when the interrupt grouping feature is available on the STM32 device, HAL_FDCAN_SetInterruptGroupsToLine() is used to assign grouped interrupts (e.g., HAL_FDCAN_IT_GROUP_STATUS_MSG and HAL_FDCAN_IT_GROUP_RX_FIFO_0) to the chosen interrupt line (line 0 and/or line 1). When interrupt grouping is not available, HAL_FDCAN_SetInterruptsToLine() is used to assign individual interrupts (e.g., HAL_FDCAN_IT_TX_COMPLETE and HAL_FDCAN_IT_RX_FIFO_0_NEW_MSG) to the chosen interrupt line (line 0 and/or line 1).

Interrupt grouping feature

HAL1

HAL2

Available

Use HAL_FDCAN_ConfigInterruptLines() with grouped interrupts (e.g., FDCAN_IT_GROUP_SMSG)

Use HAL_FDCAN_SetInterruptGroupsToLine() to assign grouped interrupts (e.g., HAL_FDCAN_IT_GROUP_STATUS_MSG)

Not available

Use HAL_FDCAN_ConfigInterruptLines() with individual interrupts (e.g., FDCAN_IT_TX_COMPLETE)

Use HAL_FDCAN_SetInterruptsToLine() to assign individual interrupts (e.g., HAL_FDCAN_IT_TX_COMPLETE)

  • Interrupt activation

    In HAL1, the function HAL_FDCAN_ActivateNotification() is used to enable specific FDCAN interrupt notifications in a single call, meaning it enables both the requested interrupts and the interrupt line(s) (line 0 and/or line 1) on which the corresponding interrupts are set.

    In HAL2, interrupt management is designed to be more granular and modular:

    • HAL_FDCAN_EnableInterruptLines() is used to activate the interrupt line(s) (line 0 and/or line 1).

    • HAL_FDCAN_EnableInterrupts() enables interrupt sources (e.g. HAL_FDCAN_IT_RX_FIFO_0_NEW_MSG).

    • For transmit complete interrupts like FDCAN_IT_TX_COMPLETE, the dedicated function HAL_FDCAN_EnableTxBufferCompleteInterrupts() must also be called to enable the corresponding buffer interrupts.

    • Similarly, for transmit abort interrupts such as FDCAN_IT_TX_ABORT_COMPLETE, the function HAL_FDCAN_EnableTxBufferCancellationInterrupts() must also be called.

    • Additionally, HAL_FDCAN_CCU_EnableInterrupts() is provided to enable clock calibration unit interrupts.

For more details see HAL FDCAN enables interrupt notifications..

Sequence diagram

  @startuml
            participant "User application" as App
  participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A
  alt #LightSteelBlue Interrupt grouping available
  App -> FDCAN: HAL_FDCAN_ConfigInterruptLines(&hfdcan, FDCAN_IT_GROUP_SMSG | FDCAN_IT_GROUP_RX_FIFO0, FDCAN_INTERRUPT_LINE0)
  else #LightCyan   else
  App -> FDCAN: HAL_FDCAN_ConfigInterruptLines(&hfdcan, FDCAN_IT_TX_COMPLETE | FDCAN_IT_RX_FIFO0_NEW_MESSAGE, FDCAN_INTERRUPT_LINE0)
  end
  FDCAN --> App:<color green>HAL_OK
  App -> FDCAN: HAL_FDCAN_ActivateNotification(&hfdcan, FDCAN_IT_TX_COMPLETE | FDCAN_IT_RX_FIFO0_NEW_MESSAGE, FDCAN_TX_BUFFER0)

  FDCAN --> App:<color green>HAL_OK

  App -> FDCAN: HAL_FDCAN_Start()
  FDCAN --> App:<color green>HAL_OK
  Note over App#lightyellow: Prepare the Tx Header

  == FDCAN HAL Message Transmit  ==
  App-> FDCAN: HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan, &TxHeader, TxData[0])
  FDCAN --> App:<color green>HAL_OK
  activate App #1000DA
  hnote over App
  <font color=blue>transmission ongoing...
  end note
  NVIC <-  : FDCAN interrupt Tx Complete
  NVIC -> FDCAN: HAL_FDCAN_IRQHandler
  FDCAN -> App: HAL_FDCAN_TxBufferCompleteCallback()
  Note over App#lightyellow: TransmissionCompleteFlag = 1U
  App --> FDCAN:
  deactivate App
  FDCAN --> NVIC:
  NVIC --> :
  deactivate App
  == FDCAN HAL Message Receive  ==
  NVIC <- : FDCAN interrupt Rx FIFO New Message
  NVIC -> FDCAN: HAL_FDCAN_IRQHandler
  FDCAN -> App: HAL_FDCAN_RxFifo0Callback()
  Note over App#lightyellow: if(RxFifo0ITs  = FDCAN_IT_RX_FIFO0_NEW_MESSAGE) \n Notification_flag  = 1U
  FDCAN <-- App
  NVIC <-- FDCAN
  NVIC --> :
  alt Notification_flag  == 1U
  App -> FDCAN: HAL_FDCAN_GetRxMessage()
  note right
     Retrieve an FDCAN frame from the Rx FIFO
  endnote

  FDCAN --> App:<color green>HAL_OK
  end

  @enduml

Code snippet

HAL1

HAL2

/* if interrupt grouping available */
HAL_FDCAN_ConfigInterruptLines(&hfdcan, FDCAN_IT_GROUP_SMSG
                                      | FDCAN_IT_GROUP_RX_FIFO0,
                                        FDCAN_INTERRUPT_LINE0);
/* else */
HAL_FDCAN_ConfigInterruptLines(&hfdcan, FDCAN_IT_TX_COMPLETE
                                      | FDCAN_IT_RX_FIFO0_NEW_MESSAGE,
                                        FDCAN_INTERRUPT_LINE0);

HAL_FDCAN_ActivateNotification(&hfdcan,
                               FDCAN_IT_TX_COMPLETE |
                               FDCAN_IT_RX_FIFO0_NEW_MESSAGE,
                               FDCAN_TX_BUFFER0);


HAL_FDCAN_Start(&hfdcan);

/* Prepare FDCAN transmit message header */
TxHeader.Identifier          = 0x111;
TxHeader.IdType              = FDCAN_STANDARD_ID;
TxHeader.TxFrameType         = FDCAN_DATA_FRAME;
TxHeader.DataLength          = FDCAN_DLC_BYTES_8;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch       = FDCAN_BRS_ON;
TxHeader.FDFormat            = FDCAN_FD_CAN;
TxHeader.TxEventFifoControl  = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;

HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan, &TxHeader, &TxData[0]);
while (TransmissionCompleteFlag == 0);

if (Notification_flag == 1)
{
HAL_FDCAN_GetRxMessage(&hfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData);
Notification_flag = 0;
}

void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
  if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
  {
    Notification_flag = 1;
  }
}

void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes)
{
  TransmissionCompleteFlag = 1U;
}
/* if interrupt grouping */
HAL_FDCAN_SetInterruptGroupsToLine(&hfdcan, HAL_FDCAN_IT_GROUP_STATUS_MSG
                                          | HAL_FDCAN_IT_GROUP_RX_FIFO_0 ,
                                            HAL_FDCAN_IT_LINE_0 );
/* else */
HAL_FDCAN_SetInterruptsToLine(&hfdcan, HAL_FDCAN_IT_TX_COMPLETE
                                    | HAL_FDCAN_IT_RX_FIFO_0_NEW_MSG ,
                                      HAL_FDCAN_IT_LINE_0 );

HAL_FDCAN_EnableInterruptLines(&hfdcan, HAL_FDCAN_IT_LINE_0);

HAL_FDCAN_EnableTxBufferCompleteInterrupts(&hfdcan, HAL_FDCAN_IT_TX_CPLT_BUFFER_0);

HAL_FDCAN_EnableInterrupts(&hfdcan, HAL_FDCAN_IT_TX_COMPLETE | HAL_FDCAN_IT_RX_FIFO_0_NEW_MSG);

HAL_FDCAN_Start(&hfdcan);

/* Prepare FDCAN transmit message header */
tx_element_header.b.identifier            = 0x111,
tx_element_header.b.identifier_type       = HAL_FDCAN_ID_STANDARD,
tx_element_header.b.frame_type            = HAL_FDCAN_FRAME_DATA,
tx_element_header.b.data_length           = HAL_FDCAN_DATA_LEN_CAN_FDCAN_8_BYTE,
tx_element_header.b.error_state_indicator = HAL_FDCAN_ERROR_STATE_IND_ACTIVE,
tx_element_header.b.bit_rate_switch       = HAL_FDCAN_BIT_RATE_SWITCH_ON,
tx_element_header.b.frame_format          = HAL_FDCAN_HEADER_FRAME_FORMAT_FD_CAN,
tx_element_header.b.event_fifo_control    = HAL_FDCAN_FIFO_STORE_TX_EVENTS,
tx_element_header.b.message_marker        = 0U,

HAL_FDCAN_ReqTransmitMsgFromFIFOQ(hfdcan, &tx_element_header, pTxData);
while (TransmissionCompleteFlag == 0);

if (Notification_flag == 1)
{
  HAL_FDCAN_GetReceivedMessage(hfdcan, HAL_FDCAN_RX_FIFO_0, &rx_element_header, RxBuffer);
  ReceptionFlag = 0;
}

static void HAL_FDCAN_RxFifo0Callback(hal_fdcan_handle_t *hfdcan, uint32_t rx_fifo0_interrupts)
{
  if((rx_fifo0_interrupts & HAL_FDCAN_IT_RX_FIFO_0_NEW_MSG) != RESET)
  {
    Notification_flag = 1;
  }
}

static void HAL_FDCAN_TxBufferCompleteCallback(hal_fdcan_handle_t *hfdcan, uint32_t buffer_indexes)
{
  TransmissionCompleteFlag = 1U;
}

Key changes

  1. HAL2 splits notification configuration into separate APIs to configure interrupts and interrupt line(s).

  2. HAL2 provides dedicated APIs for enabling Tx buffer complete interrupts.